#include "../include/stm32mp157_rcc.h"
#include "../include/stm32mp157_uart.h"
#include "../include/stm32mp157_gpio.h"

void uart_init(void)
{
    /*使能UART4,GPIOG,GPIOB外设时钟*/
    RCC->MP_APB1ENSETR |= (1UL << 16);//UART4
    RCC->MP_AHB4ENSETR |= (1UL << 6 | 1UL << 1);//GPIOG,GPIOB

    /*配置管脚为UART收发模式,TX是PG11，RX是PB2*/
    GPIOG->MODER &= ~(3UL << 22);
    GPIOG->MODER |= (2UL << 22);//AFmode
    GPIOB->MODER &= ~(3UL << 4);
    GPIOB->MODER |= (2UL << 4);//AFmode

    GPIOG->AFRH &= ~(15UL << 12);
    GPIOG->AFRH |= (6UL << 12);//PG11的AF6功能
    GPIOB->AFRL &= ~(15UL << 8);
    GPIOB->AFRL |= (8UL << 8);//PB2的AF8功能

    /*USART4寄存器配置115200 8n1 non-fifo [8n1]8位数据位，无校验位，1位停止位*/
    USART4->CR1 &= ~(1UL << 0);//先失能USART4做配置
    USART4->CR1 &= ~(1UL << 29);//清除FIFOEN位，失能，这时候读写智能一个字节一个字节，并且还要关心TXE，RXNE
    USART4->CR1 &= ~(1UL << 12 || 1UL << 28);//将m0,m1清0，[00]对应1位起始位，8位数据位，n位停止位
    USART4->CR1 &= ~(1UL << 15);//将OVER8清0,16倍过采样，在电平中间采样
    USART4->CR1 &= ~(1UL << 10);//将PCE位清0，失能奇偶校验位
    USART4->CR2 &= ~(1UL << 19);//LSB，先从低位收起
    USART4->CR2 &= ~(3UL << 12);//将STOP位置为00，[00]1位停止位
    USART4->PRESC &= ~(15UL << 0);//将PRESCALER位置为0000,1分频
    USART4->BRR |= (0x022B);//115200的波特率

    USART4->CR1 |= (1<<2);//RE位置1，接收使能
	USART4->CR1 |= (1<<3);//TE位置1，发送使能
    USART4->CR1 |= (1UL << 0);//UE位置1，使能USART4
}

void uart_putc(const char c)
{
    while(!(USART4->ISR & (1UL << 7)));//轮询ISR中断状态寄存器的TXE位，发送空闲，[1]空闲，[0]繁忙，繁忙的话就先死循环，阻塞

    USART4->TDR = c;

    if(c == '\n')
        uart_putc('\r');
    
}

void uart_puts(const char *str)
{
	while(*str)//'\0;就终止
    {
		uart_putc(*str);
		str++;
	}
}

char uart_getc(void)
{
	/*轮询接收寄存器是否为空*/
	while(!(USART4->ISR & (1<<5)));//轮询ISR中断状态寄存器的RXNE，接受非空，[1]有内容，[0]无内容，无内容的时候就一直是阻塞
	return (char)USART4->RDR;
}
int uart_gets(char *buf, int len)
{
	int i = 0 ;
	char ch;
	while(i < (len-1))
    {
		ch = uart_getc();//接收一个字符
		
        if(ch == 0x08 && i == 0)
            continue;

        uart_putc(ch); //回显
		buf[i] = ch;
        if(ch == 0x08)
        {
            uart_putc(' ');
            uart_putc(0x08);
            i--;
            continue;
        }
        
		if (ch == '\r')//用户按下了回车键
        { 
			break;
		}
		i++;
	}
	buf[i] = '\0';
	return i;
}
